{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "SzKwuqYESWwm"
   },
   "source": [
    "##### Copyright 2023 The Cirq Developers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "cellView": "form",
    "id": "4yPUsdJxSXFq"
   },
   "outputs": [],
   "source": [
    "# @title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
    "# you may not use this file except in compliance with the License.\n",
    "# You may obtain a copy of the License at\n",
    "#\n",
    "# https://www.apache.org/licenses/LICENSE-2.0\n",
    "#\n",
    "# Unless required by applicable law or agreed to in writing, software\n",
    "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
    "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
    "# See the License for the specific language governing permissions and\n",
    "# limitations under the License."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "dVkNQc0WSIwk"
   },
   "source": [
    "# Google Internal Gates in Cirq"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "zC1qlUJoSXhm"
   },
   "source": [
    "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://quantumai.google/cirq/google/internal_gates\"><img src=\"https://quantumai.google/site-assets/images/buttons/quantumai_logo_1x.png\" />View on QuantumAI</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/quantumlib/Cirq/blob/main/docs/google/internal_gates.ipynb\"><img src=\"https://quantumai.google/site-assets/images/buttons/colab_logo_1x.png\" />Run in Google Colab</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://github.com/quantumlib/Cirq/blob/main/docs/google/internal_gates.ipynb\"><img src=\"https://quantumai.google/site-assets/images/buttons/github_logo_1x.png\" />View source on GitHub</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a href=\"https://storage.googleapis.com/tensorflow_docs/Cirq/docs/google/internal_gates.ipynb\"><img src=\"https://quantumai.google/site-assets/images/buttons/download_icon_1x.png\" />Download notebook</a>\n",
    "  </td>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "id": "bd9529db1c0b"
   },
   "outputs": [],
   "source": [
    "try:\n",
    "    import cirq\n",
    "    import cirq_google\n",
    "except ImportError:\n",
    "    print(\"installing cirq...\")\n",
    "    !pip install --quiet cirq\n",
    "    print(\"installed cirq.\")\n",
    "    import cirq\n",
    "    import cirq_google"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "4783c659ce5d"
   },
   "source": [
    "Google has a wealth of gates implemented internally that don't exist or have equivalents in Cirq. `cirq_google.InternalGate` allows the creation of Cirq circuits that contain place holder operations that will get translated to the correct internal gate."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "9bdd7b2ebcbc"
   },
   "source": [
    "## InternalGate\n",
    "Instances of [cirq_google.InternalGate](https://github.com/quantumlib/Cirq/blob/61d967112ba23cc839b0e922bd42878024a3e738/cirq-google/cirq_google/ops/internal_gate.py#L20) act as placeholder objects for google internal gates. During translation, the correct gate is identified through the `gate_module` and `gate_name` properties. Then an instance of that gate is created using the `kwargs` arguments passed to the `InternalGate` constructor."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "id": "aecb9afa09a0"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "cirq_google.InternalGate(gate_name=\"GATE_NAME\", gate_module=\"GATE_MODULE\", num_qubits=2, )"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "internal_gate_args = {\n",
    "    # Arguments to be passed to the constructor of the internal gate.\n",
    "}\n",
    "internal_gate = cirq_google.InternalGate(\n",
    "    gate_module='GATE_MODULE',  # Module of class.\n",
    "    gate_name='GATE_NAME',  # Class name.\n",
    "    num_qubits=2,  # Number of qubits that the gate acts on.\n",
    "    **internal_gate_args,\n",
    ")\n",
    "internal_gate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "id": "f28062274ada"
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"overflow: auto; white-space: pre;\">0: ───GATE_MODULE.GATE_NAME()───\n",
       "      │\n",
       "1: ───#2────────────────────────</pre>"
      ],
      "text/plain": [
       "0: ───GATE_MODULE.GATE_NAME()───\n",
       "      │\n",
       "1: ───#2────────────────────────"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cirq.Circuit(internal_gate(*cirq.LineQubit.range(2)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "db0cf657ffea"
   },
   "source": [
    "## Notes\n",
    "1. InternalGate is serializable.\n",
    "1. Values of `kwargs` must be serializable as [api.v2.ArgValue](https://github.com/quantumlib/Cirq/blob/61d967112ba23cc839b0e922bd42878024a3e738/cirq-google/cirq_google/api/v2/program.proto#L281)\n",
    "1. If a value is not serializable as `api.v2.ArgValue` (e.g. a value with unit) then the translator will need to updated to know what to do for that gate."
   ]
  }
 ],
 "metadata": {
  "colab": {
   "name": "internal_gates.ipynb",
   "toc_visible": true
  },
  "kernelspec": {
   "display_name": "Python 3",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
